﻿using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Actions;
using DevExpress.ExpressApp.Blazor.SystemModule;
using DevExpress.ExpressApp.SystemModule;
using DevExpress.Persistent.Base;
using DevExpress.Utils.CommonDialogs.Internal;
using Nito.AsyncEx;

namespace EasyXaf.BlazorTabbedMdi;

public class MdiWindowViewController : ObjectViewController<ListView, MdiWindow>
{
    public SimpleAction ActiveAction { get; }

    public SimpleAction SaveAction { get; }

    public SimpleAction CloseAction { get; }

    public MdiWindowViewController()
    {
        TargetViewNesting = Nesting.Nested;

        ActiveAction = new SimpleAction(this, "ActiveWindow", PredefinedCategory.Edit)
        {
            Caption = "激活",
            ImageName = "Actions_Window"
        };

        SaveAction = new SimpleAction(this, "SaveAction", PredefinedCategory.Edit)
        {
            Caption = "保存",
            ImageName = "Action_Save_New"
        };

        CloseAction = new SimpleAction(this, "CloseWindow", PredefinedCategory.Edit)
        {
            Caption = "关闭",
            ImageName = "Action_Close"
        };
    }

    private void UpdateActionState()
    {
        var windows = View.SelectedObjects.OfType<MdiWindow>().ToList();
        ActiveAction.Enabled.SetItemValue("SelectedCount", windows.Count == 1);
        SaveAction.Enabled.SetItemValue("UnsavedCount", windows.Any(w => w.HasUnsavedChanges));
        CloseAction.Enabled.SetItemValue("SelectedCount", windows.Any());
    }

    protected override void OnActivated()
    {
        base.OnActivated();

        Frame.SetControllerActive<FilterController>(false);
        Frame.SetControllerActive<ColumnChooserController>(false);
        Frame.SetControllerActive<ListViewProcessCurrentObjectController>(false);

        ActiveAction.Execute += ActiveAction_Execute;
        SaveAction.Execute += SaveAction_Execute;
        CloseAction.Execute += CloseAction_Execute;
        View.SelectionChanged += View_SelectionChanged;

        UpdateActionState();
    }

    protected override void OnDeactivated()
    {
        ActiveAction.Execute -= ActiveAction_Execute;
        SaveAction.Execute -= SaveAction_Execute;
        CloseAction.Execute -= CloseAction_Execute;
        View.SelectionChanged -= View_SelectionChanged;

        base.OnDeactivated();
    }

    private void ActiveAction_Execute(object sender, SimpleActionExecuteEventArgs e)
    {
        if (Application.MainWindow.Template is MdiMainWindowTemplate template)
        {
            var window = e.SelectedObjects.OfType<MdiWindow>().FirstOrDefault();
            if (window != null)
            {
                template.ShowWindow(window.Window);
                ((NestedFrame)Frame).ViewItem.View.Close();
            }
        }
    }

    private void SaveAction_Execute(object sender, SimpleActionExecuteEventArgs e)
    {
        if (Application.MainWindow.Template is MdiMainWindowTemplate template)
        {
            var windows = e.SelectedObjects.OfType<MdiWindow>().Where(w => w.HasUnsavedChanges).ToList();
            foreach (var window in windows)
            {
                window.Window.View.ObjectSpace.CommitChanges();
                window.RaisePropertyChanged();
            }
            View.Refresh(true);
        }
    }

    private void CloseAction_Execute(object sender, SimpleActionExecuteEventArgs e)
    {
        if (Application.MainWindow.Template is MdiMainWindowTemplate template)
        {
            var collectionSource = View.CollectionSource;
            var windows = e.SelectedObjects.OfType<MdiWindow>().ToList();
            var hasUnsavedChanges = windows.Any(w => w.HasUnsavedChanges);
            AsyncContext.Run(async () =>
            {
                if (!hasUnsavedChanges || await template.ShowConfirmationDialogAsync() == DialogResult.Yes)
                {
                    foreach (var window in windows)
                    {
                        collectionSource.Remove(window);
                        await template.CloseWindowAsync(window.Window, true);
                    }
                }
            });
        }
    }

    private void View_SelectionChanged(object sender, EventArgs e)
    {
        UpdateActionState();
    }
}
